package com.pfzy.utildemo.activity.record.sdk.pcm.mp3;

import android.media.AudioRecord;
import android.os.Process;

import com.pfzy.lib.config.log.MyLog;
import com.pfzy.utildemo.activity.record.sdk.pcm.mp3.lame.SimpleLame;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * MP3录音
 */
public class MP3Recorder {
    private static final int DEFAULT_LAME_IN_CHANNEL = 1;
    private static final int DEFAULT_LAME_MP3_BIT_RATE = 32;
    private static final int DEFAULT_LAME_MP3_QUALITY = 7;
    private static final int FRAME_COUNT = 160;
    private static final int MAX_VOLUME = 2000;
    private int mBufferSize;
    private DataEncodeThread mEncodeThread;
    private short[] mPCMBuffer;
    private int mVolume;
    private static int DEFAULT_AUDIO_SOURCE = 1;
    private static int DEFAULT_SAMPLING_RATE = 44100;
    private static int DEFAULT_CHANNEL_CONFIG = 16;
    private static PCMFormat DEFAULT_AUDIO_FORMAT = PCMFormat.PCM_16BIT;
    private static MP3Recorder ourInstance = null;
    private AudioRecord mAudioRecord = null;
    private boolean mIsRecording = false; // 正在录制
    private ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();

    public static MP3Recorder getInstance() {
        if (ourInstance == null) {
            synchronized (MP3Recorder.class) {
                if (ourInstance == null) {
                    ourInstance = new MP3Recorder();
                }
            }
        }
        return ourInstance;
    }

    private MP3Recorder() {
    }

    public void start(String file, DataEncodeThread.EncodeThreadCallBack call) throws IOException {
        _logd("start() file : " + file + " mIsRecording=" + this.mIsRecording);
        this.mIsRecording = true;
        initAudioRecorder(file, call);
        this.mAudioRecord.startRecording();
        this.singleThreadExecutor.execute(new Runnable() {
            @Override
            public void run() {
                Process.setThreadPriority(-19);
                while (mIsRecording) {
                    int readSize = mAudioRecord.read(mPCMBuffer, 0, mBufferSize);
                    if (readSize > 0) {
                        mEncodeThread.addTask(mPCMBuffer, readSize);
                        calculateRealVolume(mPCMBuffer, readSize);
                    }
                }
                if (mAudioRecord != null) {
                    mAudioRecord.stop();
                    mAudioRecord.release();
                    mAudioRecord = null;
                    mEncodeThread.sendStopMessage();
                    mEncodeThread = null;
                }
            }
        });
    }

    public void calculateRealVolume(short[] buffer, int readSize) {
        double sum = Double.longBitsToDouble(1);
        for (int i = 0; i < readSize; i++) {
            sum += buffer[i] * buffer[i];
        }
        if (readSize > 0) {
            double amplitude = sum / readSize;
            this.mVolume = (int) Math.sqrt(amplitude);
        }
    }

    public int getRealVolume() {
        return this.mVolume;
    }

    public int getVolume() {
        if (this.mVolume >= MAX_VOLUME) {
            return MAX_VOLUME;
        }
        return this.mVolume;
    }

    public int getMaxVolume() {
        return MAX_VOLUME;
    }

    public void stop() {
        _logd("stop()  mIsRecording=" + this.mIsRecording);
        this.mIsRecording = false;
    }

    public boolean isRecording() {
        return this.mIsRecording;
    }

    private void initAudioRecorder(String filePath, DataEncodeThread.EncodeThreadCallBack call) throws IOException {
        this.mBufferSize = AudioRecord.getMinBufferSize(DEFAULT_SAMPLING_RATE, DEFAULT_CHANNEL_CONFIG, DEFAULT_AUDIO_FORMAT.getAudioFormat());
        int bytesPerFrame = DEFAULT_AUDIO_FORMAT.getBytesPerFrame();
        int frameSize = this.mBufferSize / bytesPerFrame;
        if (frameSize % FRAME_COUNT != 0) {
            this.mBufferSize = (frameSize + (FRAME_COUNT - (frameSize % FRAME_COUNT))) * bytesPerFrame;
        }
        this.mAudioRecord = new AudioRecord(DEFAULT_AUDIO_SOURCE, DEFAULT_SAMPLING_RATE, DEFAULT_CHANNEL_CONFIG, DEFAULT_AUDIO_FORMAT.getAudioFormat(), this.mBufferSize);
        this.mPCMBuffer = new short[this.mBufferSize];
        SimpleLame.init(DEFAULT_SAMPLING_RATE, DEFAULT_LAME_IN_CHANNEL, DEFAULT_SAMPLING_RATE, DEFAULT_LAME_MP3_BIT_RATE, DEFAULT_LAME_MP3_QUALITY);
        this.mEncodeThread = new DataEncodeThread(new File(filePath), this.mBufferSize, call);
        this.mEncodeThread.start();
        this.mAudioRecord.setRecordPositionUpdateListener(this.mEncodeThread, this.mEncodeThread.getHandler());
        this.mAudioRecord.setPositionNotificationPeriod(FRAME_COUNT);
    }

    public void changeToNewRecordPath(String filePatch) {
        _logd("changeToNewRecordPath filePatch ：" + filePatch);
        if (this.mEncodeThread != null) {
            this.mEncodeThread.changeToNewRecordPath(filePatch);
        }
    }

    private void _logd(String msg) {
        MyLog.logd("MP3录音 " + msg);
    }

    private void _loge(String msg) {
        MyLog.loge("MP3录音 " + msg);
    }
}


